package localdatabase

import (
	"fmt"
	"github.com/glebarez/sqlite"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
	"gorm.io/gorm/schema"
	"sync"
	"time"
)

// GormDBManager GORM数据库管理器
type GormDBManager struct {
	instances map[string]*gorm.DB
	mu        sync.RWMutex
}

var (
	// 全局的GormDBManager实例
	gormManager     *GormDBManager
	gormManagerOnce sync.Once
)

// GetGormDBManager 获取GormDBManager的单例实例
func GetGormDBManager() *GormDBManager {
	gormManagerOnce.Do(func() {
		gormManager = &GormDBManager{
			instances: make(map[string]*gorm.DB),
		}
	})
	return gormManager
}

// GetDB 获取指定路径的GORM实例，如果不存在则创建
func (m *GormDBManager) GetDB(filePath string) (*gorm.DB, error) {
	// 首先尝试从缓存获取
	m.mu.RLock()
	db, exists := m.instances[filePath]
	m.mu.RUnlock()

	if exists {
		return db, nil
	}

	// 不存在则创建新实例
	db, err := m.createDB(filePath)
	return db, err
}

// createDB 创建新的GORM实例
func (m *GormDBManager) createDB(filePath string) (*gorm.DB, error) {
	fmt.Println(filePath)
	// 创建GORM配置
	gormConfig := &gorm.Config{
		Logger: logger.Default.LogMode(logger.Error),
		NamingStrategy: schema.NamingStrategy{
			SingularTable: true, // 使用单数表名
		},
		// 全局模式，使用软删除
		QueryFields: true, // 根据字段名称查询
	}

	// 创建数据库连接
	// 添加共享模式和超时参数到DSN
	dsn := fmt.Sprintf("file:%s?cache=shared&mode=rwc&_journal_mode=WAL&_timeout=15000&_busy_timeout=15000", filePath)
	db, err := gorm.Open(sqlite.Open(dsn), gormConfig)
	if err != nil {
		// 尝试使用只读模式连接
		dsnReadOnly := fmt.Sprintf("file:%s?mode=ro&_query_only=true", filePath)
		db, err = gorm.Open(sqlite.Open(dsnReadOnly), gormConfig)
		if err != nil {
			return nil, fmt.Errorf("无法打开数据库连接: %w", err)
		}
		fmt.Println("警告: 数据库以只读模式打开，因为它已被其他进程锁定")
	} else {
		fmt.Println("Open db ok")
	}

	// 设置连接池
	sqlDB, err := db.DB()
	if err != nil {
		return nil, fmt.Errorf("无法获取底层数据库连接: %w", err)
	}

	// 设置连接池参数
	sqlDB.SetMaxIdleConns(10)
	sqlDB.SetMaxOpenConns(100)
	sqlDB.SetConnMaxLifetime(time.Hour)

	// 存储实例
	m.mu.Lock()
	m.instances[filePath] = db
	m.mu.Unlock()

	return db, nil
}

// CloseDB 关闭特定的数据库连接
func (m *GormDBManager) CloseDB(filePath string) error {
	m.mu.Lock()
	defer m.mu.Unlock()

	db, exists := m.instances[filePath]
	if !exists {
		return fmt.Errorf("数据库实例不存在: %s", filePath)
	}

	sqlDB, err := db.DB()
	if err != nil {
		return fmt.Errorf("获取底层数据库连接失败: %w", err)
	}

	if err := sqlDB.Close(); err != nil {
		return fmt.Errorf("关闭数据库连接失败: %w", err)
	}

	delete(m.instances, filePath)
	return nil
}

// CloseAll 关闭所有数据库连接
func (m *GormDBManager) CloseAll() []error {
	m.mu.Lock()
	defer m.mu.Unlock()

	var errs []error
	for path, db := range m.instances {
		sqlDB, err := db.DB()
		if err != nil {
			errs = append(errs, fmt.Errorf("获取底层数据库连接失败 %s: %w", path, err))
			continue
		}

		if err := sqlDB.Close(); err != nil {
			errs = append(errs, fmt.Errorf("关闭数据库连接失败 %s: %w", path, err))
		}
	}

	// 清空实例
	m.instances = make(map[string]*gorm.DB)
	return errs
}

// AutoMigrate 自动迁移数据表结构
func (m *GormDBManager) AutoMigrate(db *gorm.DB, models ...interface{}) error {
	return db.AutoMigrate(models...)
}

// RegisterModel 注册模型并自动创建表
func (m *GormDBManager) RegisterModel(db *gorm.DB, models ...interface{}) error {
	return m.AutoMigrate(db, models...)
}
